// 缩放状态
// 0正常
// 1小于最小缩放倍数
// 2大于最大缩放倍数
enum ScaleStatus {
    Normal,
    OverSizeMin,
    OverSizeMax,
}
// 刻度尺类
interface IRuleDrawer {
    init(): CanvasRenderingContext2D | null;
    changeScale(scale: number): void;
    drawRule(): void;
    increaseScale(): void;
    reduceScale(): void;
    reset(): void;
    translateRule(n:number): void;
    resetRuleByProp(prop:IDrawRuleConfig):void;
}
// 定义配置接口
interface IDrawRuleConfig {
    width?: number;
    height?: number;
    type?: "x" | "y";
    scale?: number;
    unitsNum?: number;
    minScale?: number;
    maxScale?: number;
    lineWidth?: number;
    lineColor?: string;
    longLineLength?: number;
    shortLineLength?: number;
    labelColor?: string;
    labelOffsetX?: number;
    labelOffsetY?: number;
    translateX?: number;
    translateDis?: number;
}

class DrawRule implements IRuleDrawer {
    [x: string]: any;
    constructor(canvas, config?: IDrawRuleConfig) {
        const initConfig = {
            width: 3000,
            height: 40,
            type: "x",
            scale: 1,
            unitsNum: 0.1, //缩放单位增加数量
            minScale: 0.1,
            maxScale: 4,
            lineWidth: 1,
            lineColor: "#FFF",
            longLineLength: 20,
            shortLineLength: 10,
            labelColor: "#FFF",
            labelOffsetX: 0,
            labelOffsetY: 0,
            translateDis: 0
        }
        this.can = canvas
        this.initConfig = Object.assign(initConfig, config)
        // 重置
        this.reset()
    }

    //初始化canvas
    init(): CanvasRenderingContext2D | null {
        if (this.can.getContext) {
            this.can.width = this.width;
            this.can.height = this.height;
            return this.can.getContext("2d");
        } else {
            console.log("浏览器暂不支持canvas");
            return null;
        }
    }

    /**
     * @description 控制缩放倍率
     * @param n {number} 缩放倍率
     * @param [fn] {function} 超过限制倍率的回调函数
     * */
    changeScale(n, fn: (status: ScaleStatus) => void = (e) => { }): void {
        let status: ScaleStatus = ScaleStatus.Normal;
        if (n > 0 && this.minScale <= n && this.maxScale >= n) {
            console.log(`当前缩放倍数${n}`);
            this.scale = n;
            this.drawRule();
        } else {
            if (this.minScale >= n) {
                status = ScaleStatus.OverSizeMin;
                console.log(`当前已经缩放到最小倍数${this.minScale}`);
            } else {
                status = ScaleStatus.OverSizeMax;
                console.log(`当前已经缩放到最大倍数${this.maxScale}`);
            }
        }
        fn(status);
    }

    //   缩放递增
    increaseScale() {
        let n = (this.scale * 10 + this.unitsNum * 10) / 10;
        this.changeScale(n);
    }
    //   缩放递增
    reduceScale() {
        let n = (this.scale * 10 - this.unitsNum * 10) / 10;
        this.changeScale(n);
    }
    // 平移
    translateRule(n) {
        this.translateDis = n;
        this.drawRule();
    }

    /**
     * @description 绘制刻度尺
     */
    drawRule(): void {
        let len = null
        this.ctx.clearRect(0, 0, this.width, this.height);
        // 刻度宽度
        this.ctx.lineWidth = this.lineWidth;
        let step = 10;
        // 刻度线数量
        let n = 0;
        this.ctx.save(); // 添加保存绘图状态
        if (this.type === 'x') {
            len = this.width
            this.ctx.translate(-this.translateDis, 0);
        } else {
            len = this.height
            this.ctx.translate(0, -this.translateDis);
        }
        for (let i = 0; i <= len + this.translateDis; i += step) {
            let lineWidth = this.shortLineLength;
            this.ctx.beginPath();
            // 刻度线颜色
            this.ctx.strokeStyle = this.lineColor;
            // 刻度值颜色
            this.ctx.fillStyle = this.labelColor;
            if (!(n % 10)) {
                lineWidth = this.longLineLength;
                this.ctx.save(); // 保存当前绘图状态
                this.ctx.textBaseline = 'top';
                if (this.type === 'x') {
                    this.ctx.translate(i, this.longLineLength);
                } else {
                    this.ctx.textAlign = 'right'
                    this.ctx.translate(this.longLineLength, i);
                    this.ctx.rotate(-90 * Math.PI / 180);
                }
                this.ctx.fillText(
                    Math.ceil(i / this.scale).toString(),
                    this.labelOffsetX,
                    this.labelOffsetY,
                );
                this.ctx.restore()

            }
            if (this.type === 'x') {
                this.ctx.moveTo(i, 0);
                this.ctx.lineTo(i, lineWidth);
            } else {
                this.ctx.moveTo(0, i);
                this.ctx.lineTo(lineWidth, i);
            }
            this.ctx.stroke();
            this.ctx.closePath();
            n++;
        }
        this.ctx.restore(); // 添加恢复绘图状态
    }
    // 修改某个属性后，重置
    resetRuleByProp(props){
        for(const key in props){
            this[key]=props[key]
            if(key==='width'||key==='height'){
                this.can[key]=this[key]
            }
        }
        this.drawRule()
    }

    //   重置
    reset(): void {
        for (let key in this.initConfig) {
            this[key] = this.initConfig[key];
        }
        this.ctx = this.init();
        if (this.ctx) {
            this.drawRule();
        }
    }
}

export default DrawRule;

